package com.mdd.front.service.comment.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.mdd.common.constant.GlobalConstant;
import com.mdd.common.core.PageResult;
import com.mdd.common.dto.GoodsCommentPageDto;
import com.mdd.common.dto.result.GoodsCommentPageResultDto;
import com.mdd.common.dto.result.OrderPageResultDto;
import com.mdd.common.entity.album.Album;
import com.mdd.common.entity.goods.Goods;
import com.mdd.common.entity.goods.GoodsComment;
import com.mdd.common.entity.goods.OrderGoods;
import com.mdd.common.entity.image.GoodsCommentImage;
import com.mdd.common.entity.order.Order;
import com.mdd.common.entity.user.User;
import com.mdd.common.enums.GoodsCommentLevelEnum;
import com.mdd.common.enums.GoodsCommentStatusEnum;
import com.mdd.common.enums.OrderStatusEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.album.AlbumMapper;
import com.mdd.common.mapper.comment.GoodsCommentMapper;
import com.mdd.common.mapper.goods.GoodsMapper;
import com.mdd.common.mapper.image.GoodsCommentImageMapper;
import com.mdd.common.mapper.order.OrderMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.utils.RandomUtil;
import com.mdd.common.utils.TimeUtil;
import com.mdd.common.utils.UrlUtil;
import com.mdd.front.LikeFrontThreadLocal;
import com.mdd.front.service.IUserService;
import com.mdd.front.service.album.impl.AlbumServiceImpl;
import com.mdd.front.service.comment.IGoodsCommentService;
import com.mdd.front.service.goods.IOrderGoodsService;
import com.mdd.front.service.order.IOrderService;
import com.mdd.front.validate.comment.GoodsCommentPageParam;
import com.mdd.front.validate.comment.GoodsCommentParam;
import com.mdd.front.vo.comment.CommentParam;
import com.mdd.front.vo.comment.GoodsCommentDetailVo;
import com.mdd.front.vo.comment.GoodsCommentListVo;
import com.mdd.front.vo.goods.StatisticsGoodsCommentVo;
import com.mdd.front.vo.goods.StatisticsGoodsUserCommentVo;
import com.mdd.front.vo.user.UserInfoVo;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 服务评价实现类
 */
@Service
public class GoodsCommentServiceImpl extends ServiceImpl<GoodsCommentMapper, GoodsComment> implements IGoodsCommentService {

    @Resource
    GoodsCommentMapper goodsCommentMapper;
    @Resource
    GoodsMapper goodsMapper;

    @Resource
    private GoodsCommentImageMapper commentImageMapper;

    @Resource
    private AlbumMapper albumMapper;

    @Resource
    private IUserService userService;
    @Resource
    private UserMapper userMapper;

    @Resource
    private IOrderService orderService;

    @Resource
    private IOrderGoodsService orderGoodsService;

    @Resource
    private OrderMapper orderMapper;

    /**
     * 服务评价列表
     *
     * @param params 搜索参数
     * @return PageResult<GoodsCommentListVo>
     */
    @Override
    public PageResult<GoodsCommentListVo> list(GoodsCommentPageParam params) {
        Page<GoodsCommentListVo> page = new Page<>(params.getPageNo(), params.getPageSize());
        GoodsCommentPageDto pageDto = new GoodsCommentPageDto();
        BeanUtils.copyProperties(params, pageDto);
        Page<GoodsCommentPageResultDto> resultDtoPage = goodsCommentMapper.pageResult(page, pageDto);
        if (resultDtoPage == null || CollectionUtils.isEmpty(resultDtoPage.getRecords())) {
            return PageResult.iPageHandle(page.getTotal(), page.getCurrent(), page.getSize(), Lists.newArrayList());
        }
        List<GoodsCommentPageResultDto> records = resultDtoPage.getRecords();
        List<Long> commentIds = records.stream().map(GoodsCommentPageResultDto::getId).collect(Collectors.toList());
        LambdaQueryWrapper<GoodsCommentImage> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(GoodsCommentImage::getCommentId, commentIds);
        List<GoodsCommentImage> commentImageList = commentImageMapper.selectList(lambdaQueryWrapper);
        Map<Long, List<GoodsCommentImage>> commentImageMap = commentImageList.stream().collect(Collectors.groupingBy(GoodsCommentImage::getCommentId));
        List<Long> userIds = records.stream().map(GoodsCommentPageResultDto::getUserId).distinct().collect(Collectors.toList());
        Map<Integer, UserInfoVo> userMap = userService.listByIds(userIds).stream().collect(Collectors.toMap(item -> item.getId(), item -> item, (a, b) -> b));
        List<GoodsCommentListVo> list = new LinkedList<>();
        // 数据转换
        for (GoodsCommentPageResultDto item : records) {
            GoodsCommentListVo vo = new GoodsCommentListVo();
            vo.setId(item.getId());
            vo.setGoodsId(item.getGoodsId());
            vo.setUserId(item.getUserId());
            vo.setUserInfoVo(userMap.get(item.getUserId().intValue()));
            vo.setOrderGoodsId(item.getOrderGoodsId());
            vo.setServiceComment(item.getServiceComment());
            vo.setComment(item.getComment());
            vo.setReply(item.getReply());
            vo.setStatus(item.getStatus());
            vo.setStatusName(GoodsCommentStatusEnum.getMap().get(vo.getStatus()));
            vo.setCommentLevel(item.getCommentLevel());
            vo.setCommentLevelName(GoodsCommentLevelEnum.getMap().get(vo.getCommentLevel()));
            if (commentImageMap.containsKey(item.getId())) {
                List<GoodsCommentImage> imageList = commentImageMap.get(item.getId());
                List<String> commentImageUrlList = Lists.newArrayList();
                for (GoodsCommentImage commentImage : imageList) {
                    commentImageUrlList.add(UrlUtil.toAbsoluteUrl(commentImage.getUri()));
                }
                vo.setCommentUrlList(commentImageUrlList);
            }
            vo.setAvatarUrl(UrlUtil.toAbsoluteUrl(item.getAvatarUri()));
            vo.setNickname(item.getNickname());
            vo.setUsername(item.getUsername());
            vo.setSn(item.getSn());
            vo.setGoodsImageUrl(UrlUtil.toAbsoluteUrl(item.getGoodsImageUri()));
            vo.setGoodsName(item.getGoodsName());
            vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            vo.setPrice(item.getPrice());
            vo.setUnitName(item.getUnitName());
            list.add(vo);
        }
        // 如果是晒图的 特殊处理删除没有图片的数据
        if (params.getCommentLevel() != null && GoodsCommentLevelEnum.PICTURE.getCode() == params.getCommentLevel()) {
            Iterator<GoodsCommentListVo> iterator = list.iterator();
            while (iterator.hasNext()) {
                GoodsCommentListVo next = iterator.next();
                if (CollectionUtils.isEmpty(next.getCommentUrlList())) {
                    iterator.remove();
                }
            }
        }
        return PageResult.iPageHandle(page.getTotal(), page.getCurrent(), page.getSize(), list);
    }

    /**
     * 服务评价详情
     *
     * @param id 主键参数
     * @return GoodsComment
     */
    @Override
    public GoodsCommentDetailVo detail(Integer id) {
        GoodsComment model = goodsCommentMapper.selectOne(
                new QueryWrapper<GoodsComment>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在");

        GoodsCommentDetailVo vo = new GoodsCommentDetailVo();
        BeanUtils.copyProperties(model, vo);
        UserInfoVo info = userService.info(model.getUserId().intValue());
        vo.setUserInfoVo(info);
        vo.setCreateTime(TimeUtil.timestampToDate(model.getCreateTime()));
        return vo;
    }

    /**
     * 服务评价新增
     *
     * @param goodsCommentParam 参数
     */
    @Override
    public void add(GoodsCommentParam goodsCommentParam) {
        Long orderId = goodsCommentParam.getOrderId();
        OrderGoods orderGoods = orderGoodsService.getByOrderId(orderId);
        Assert.isTrue(orderGoods.getIsComment() == 0,"商品已评价完成！");
        Order order = orderService.getById(goodsCommentParam.getOrderId(), LikeFrontThreadLocal.getUserId());
        if (OrderStatusEnum.FINISHED.getStatus() != order.getOrderStatus()) {
            throw new OperateException("订单未完成,不能进行评价");
        }
        GoodsComment model = new GoodsComment();
        model.setGoodsId(goodsCommentParam.getGoodsId());
        model.setUserId(goodsCommentParam.getUserId());
        model.setOrderGoodsId(goodsCommentParam.getOrderId());
        model.setServiceComment(goodsCommentParam.getServiceComment());
        model.setComment(goodsCommentParam.getComment());
        model.setCommentLevel(goodsCommentParam.getCommentLevel());
        model.setCreateTime(TimeUtil.timestamp());
        model.setUpdateTime(TimeUtil.timestamp());
        goodsCommentMapper.insert(model);
        if (CollectionUtils.isNotEmpty(goodsCommentParam.getCommentImages())) {
            List<String> commentImages = goodsCommentParam.getCommentImages();
            for (String commentImage : commentImages) {
                String relativeUrl = UrlUtil.toRelativeUrl(commentImage);
                GoodsCommentImage image = new GoodsCommentImage();
                image.setCommentId(model.getId());
                image.setUri(relativeUrl);
                commentImageMapper.insert(image);
            }
        }
        //更新商品评价状态
        orderGoods.setIsComment(1);
        orderGoods.setUpdateTime(TimeUtil.timestamp());
        orderGoodsService.updateEntityById(orderGoods);
    }

    @Override
    public StatisticsGoodsUserCommentVo statistics(Long userId) {
        StatisticsGoodsUserCommentVo commentVo = new StatisticsGoodsUserCommentVo();
        List<OrderPageResultDto> list = orderMapper.listFinishOrder(userId);
        if (CollectionUtils.isEmpty(list)) {
            return commentVo;
        }
        Long waitCommentCount = list.stream().filter(item -> item.getIsComment() == 0).count();
        commentVo.setCommentCount(list.size() - waitCommentCount);
        commentVo.setWaitCommentCount(waitCommentCount);
        return commentVo;
    }

    @Override
    public GoodsCommentDetailVo getLastCommentByGoodsId(Long goodsId) {
        LambdaQueryWrapper<GoodsComment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(GoodsComment::getGoodsId, goodsId);
        lambdaQueryWrapper.orderByDesc(GoodsComment::getCreateTime);
        lambdaQueryWrapper.last("limit 1");
        GoodsComment model = super.getOne(lambdaQueryWrapper);
        if (null == model) {
            return null;
        }
        GoodsCommentDetailVo detailVo = new GoodsCommentDetailVo();
        BeanUtils.copyProperties(model, detailVo);
        detailVo.setCreateTime(TimeUtil.timestampToDate(model.getCreateTime()));
        UserInfoVo info = userService.info(detailVo.getUserId().intValue());
        detailVo.setUserInfoVo(info);
        return detailVo;
    }

    @Override
    public StatisticsGoodsCommentVo statisticsGoods(Long goodsId) {
        StatisticsGoodsCommentVo vo = new StatisticsGoodsCommentVo();
        LambdaQueryWrapper<GoodsComment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(GoodsComment::getGoodsId, goodsId);
        lambdaQueryWrapper.eq(GoodsComment::getIsDelete, GlobalConstant.NOT_DELETE);
        List<GoodsComment> list = super.list(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return vo;
        }
        long goodCount = list.stream().map(GoodsComment::getCommentLevel).filter(item -> GoodsCommentLevelEnum.GOOD_COMMENT.getCode() == item).count();
        long generalCount = list.stream().map(GoodsComment::getCommentLevel).filter(item -> GoodsCommentLevelEnum.GENERALLY_COMMENT.getCode() == item).count();
        long badCount = list.stream().map(GoodsComment::getCommentLevel).filter(item -> GoodsCommentLevelEnum.BAD_COMMENT.getCode() == item).count();
        List<Long> commentIds = list.stream().map(GoodsComment::getId).collect(Collectors.toList());
        int pictureCount = 0;
        LambdaQueryWrapper<GoodsCommentImage> imageLambdaQueryWrapper = new LambdaQueryWrapper<>();
        imageLambdaQueryWrapper.in(GoodsCommentImage::getCommentId, commentIds);
        List<GoodsCommentImage> imageList = commentImageMapper.selectList(imageLambdaQueryWrapper);
        if (CollectionUtils.isNotEmpty(imageList)) {
            pictureCount = (int) imageList.stream().map(GoodsCommentImage::getCommentId).distinct().count();
        }
        vo.setTotalCount(list.size());
        vo.setGoodCount((int) goodCount);
        vo.setGeneralCount((int) generalCount);
        vo.setBadCount((int) badCount);
        vo.setPictureCount(pictureCount);
        return vo;
    }

    @Override
    public List<GoodsComment> listByUserId(Long userId) {
        LambdaQueryWrapper<GoodsComment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(GoodsComment::getUserId, userId);
        lambdaQueryWrapper.eq(GoodsComment::getIsDelete, GlobalConstant.NOT_DELETE);
        return super.list(lambdaQueryWrapper);
    }

    @Override
    public List<GoodsComment> listByOrderIds(List<Long> orderIds) {
        LambdaQueryWrapper<GoodsComment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(GoodsComment::getOrderGoodsId, orderIds);
        List<GoodsComment> list = super.list(lambdaQueryWrapper);
        return list;
    }

    @Override
    public GoodsComment listByOrderId(Long orderId) {
        LambdaQueryWrapper<GoodsComment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(GoodsComment::getOrderGoodsId, orderId);
        lambdaQueryWrapper.last("limit 1");
        return super.getOne(lambdaQueryWrapper);
    }

    @Override
    @Transactional
    public void addGoodsComment(CommentParam params) {

        // 获取 人机
        List<Integer> users = userMapper.selectList(new LambdaQueryWrapper<User>()
                        .like(User::getNickname, "***")).stream()
                .map(User::getId).collect(Collectors.toList());
        // 获取 评论
        List<String> comments = params.getComment();
        // 获取 图片
        List<String> urls = params.getUrl();
        Map<String, Integer> collect = albumMapper.selectList(new LambdaQueryWrapper<Album>().in(Album::getUri, urls))
                                        .stream().collect(Collectors.toMap(Album::getUri, Album::getId));
        int urlNum = comments.size() / collect.size();
        Set<String> strings = collect.keySet();
        urls = new ArrayList<>(strings);
        AtomicInteger count = new AtomicInteger(0);
        Random random = new Random();
        for (String comment : comments) {
            GoodsComment goodsComment = new GoodsComment(params.getGoodId());
            int randomNumber = random.nextInt(100);
            if (users.size()<0){
                    users = userMapper.selectList(new LambdaQueryWrapper<User>()
                            .like(User::getNickname, "***")).stream()
                            .map(User::getId).collect(Collectors.toList());
            }
            // 获取随机用户
            Integer randomUserID = RandomUtil.getRandomItem(users);
            goodsComment.setUserId(Long.valueOf(randomUserID));
            int serviceNumbeer = (randomNumber < 20) ? 2 :
                                 ((randomNumber < 40) ? 3 :
                                         ((randomNumber < 70) ? 4 : 5));
            goodsComment.setServiceComment(serviceNumbeer);
            randomNumber = goodsComment.getServiceComment();
            int levelNumber = (serviceNumbeer > 3) ? 1 :
                    ((randomNumber > 1) ? 2 : 3);
            goodsComment.setCommentLevel(levelNumber);
            Long nowTime =  params.getstartTime() + random.nextInt(params.getEnTime().intValue()-params.getstartTime().intValue());
            goodsComment.setCreateTime(nowTime);
            goodsComment.setGoodsId(Long.valueOf(params.getGoodId()));
            goodsComment.setComment(comment);
            if (params.getNot()==1) {
                goodsComment.setCommentLevel(3);
                goodsComment.setServiceComment((random.nextInt(100) < 70) ? 1 : 2);
            }
            // 添加评论
            goodsCommentMapper.insert(goodsComment);
            // 获取图片
            if( !strings.isEmpty() && count.getAndIncrement() % urlNum == 0  ){
                List<String> commentUrls = RandomUtil.getRandomItem(urls,GlobalConstant.THREE);
                List<GoodsCommentImage> imageList = new ArrayList<>();
                for (String commentUrl: commentUrls) {
                    Album album = albumMapper.selectOne(new LambdaQueryWrapper<Album>().eq(Album::getId,collect.get(commentUrl)).eq(Album::getUid,0));
                    if (album != null && randomNumber>2) {
                        GoodsCommentImage goodsCommentImage = new GoodsCommentImage(goodsComment.getId(), commentUrl);
                        imageList.add(goodsCommentImage);
                        album.setUid(1);
                        goodsComment.setServiceComment(randomNumber);
                        goodsComment.setCommentLevel(1);
                        albumMapper.updateById(album);
                        commentImageMapper.insert(goodsCommentImage);
                    }
                    goodsCommentMapper.updateById(goodsComment);
                }
                strings.removeAll(commentUrls);
            }
            users.remove(users);
        }
        Goods goods = goodsMapper.selectById(params.getGoodId());
        goods.setOrderNum(goods.getOrderNum()+ comments.size());
        goodsMapper.updateById(goods);
    }
}
